package com.cip.webapp.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.springframework.mail.MailException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import com.cip.admin.dao.UserDao;
import com.cip.admin.model.Role;
import com.cip.admin.model.User;
import com.cip.admin.service.UserExistsException;
import com.cip.common.Constants;
import com.cip.master.model.Academic;
import com.cip.master.model.ClassYear;
import com.cip.master.model.Event;
import com.cip.master.model.Section;
import com.cip.master.service.ClassYearService;
import com.cip.master.service.EventService;
import com.cip.master.service.SectionService;
import com.cip.webapp.util.RequestUtil;
import com.cip.common.util.SecurityUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Action for facilitating User Management feature.
 */
public class CandidateAction extends BaseAction {
    private static final long serialVersionUID = 6876558938712115191L;
    public static final Log logger = LogFactory.getLog( com.cip.webapp.action.CandidateAction.class);
    private List<User> users;
    private User user;
    private String id;
    private String query;
    private ClassYearService classYearService;
    private SectionService sectionService;
	private List<ClassYear> classYears;
	private List<Section> sections;
	private String currentPassword;
	private String password;
	private List<Event> events;
	private EventService eventService;
	
	private File upload;
	private String uploadFileName;
	List<Map<String, String>> listofmap;
    /**
     * Holder for users to display on list screen
     *
     * @return list of users
     */
    public List<User> getUsers() {
        return users;
    }

    public void setId(String id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
    public File getUpload() {
        return upload;
    }

    public void setUpload(File file) {
        this.upload = upload;
    }
    
    public void setQ(String q) {
        this.query = q;
    }
    
    public String getUploadFileName(){
    	return uploadFileName;
    }
    
    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }
    public String getCurrentPassword(){
    	return currentPassword;
    }
    
    public void setCurrentPassword(String currentPassword) {
        this.currentPassword = currentPassword;
    }
    
    public String getPassword(){
    	return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public List<Map<String, String>> getListofmap() {
		return listofmap;
	}

	public void setListofmap(List<Map<String, String>> listofmap) {
		this.listofmap = listofmap;
	}

	/**
     * Delete the user passed in.
     *
     * @return success
     */
    public String delete() {
        userManager.removeUser(user.getId().toString());
        List<Object> args = new ArrayList<Object>();
        args.add(user.getFullName());
        saveMessage(getText("user.deleted", args));

        return SUCCESS;
    }

    /**
     * Sends users to "mainMenu" when !from.equals("list"). Sends everyone else to "cancel"
     *
     * @return "mainMenu" or "cancel"
     */
    public String cancel() {
      /*  if (!"list".equals(from)) {
            return "mainMenu";
        }*/
        return "cancel";
    }

     
    /**
     * Save Candidate
     *
     * @return success if everything worked, otherwise input
     * @throws Exception when setting "access denied" fails on response
     */
    public String saveCandidate() throws Exception {
        Integer originalVersion = user.getVersion();

        boolean isNew = ("".equals(getRequest().getParameter("user.version")));
        /*// only attempt to change roles if user is admin
        // for other users, prepare() method will handle populating
        if (getRequest().isUserInRole(Constants.ADMIN_ROLE)) {
            user.getRoles().clear(); // APF-788: Removing roles from user doesn't work
            String[] userRoles = getRequest().getParameterValues("userRoles");

            for (int i = 0; userRoles != null && i < userRoles.length; i++) {
                String roleName = userRoles[i];
                user.addRole(roleManager.getRole(roleName));
            }
        }*/
        User loggedInUser = SecurityUtil.getLoggedInUser();
        try {
        	user.addRole(roleManager.getRole(Constants.USER_ROLE));
        	//user.setPassword(user.getUsername().toLowerCase());
        	//user.setConfirmPassword(user.getUsername().toLowerCase());       	
        	
        	user.setTenantId(loggedInUser.getTenantId());
        	user.setEnabled(true);
            userManager.saveUser(user);
        } catch (AccessDeniedException ade) {
            // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity
            log.warn(ade.getMessage());
            getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        } catch (UserExistsException e) {
            List<Object> args = new ArrayList<Object>();
            args.add(user.getUsername());
            args.add(user.getEmail());
            addActionError(getText("errors.existing.user", args));
            // reset the version # to what was passed in
            user.setVersion(originalVersion);
            // redisplay the unencrypted passwords
            user.setPassword(user.getConfirmPassword());
            return INPUT;
        }
        setClassYears(classYearService.getAllClassYear());
    	setSections(sectionService.getAllSection());
    	user.setClassYear(user.getClassYear());
    	
         // add success messages
        List<Object> args = new ArrayList<Object>();
        args.add(user.getFullName());
        if (isNew) {
        	saveMessage(getText("user.added", args));
            // Send an account information e-mail
            mailMessage.setSubject(getText("signup.email.subject"));
            try {
                 sendUserMessage(user, getText("newuser.email.message", args), RequestUtil.getAppURL(getRequest()));
            } catch (MailException me) {
            	logger.error("Error occured while sending email for account" +me.getMessage()+" for the tenant "+loggedInUser.getTenantId());
                // addActionError(me.getCause().getLocalizedMessage());
            }
            return SUCCESS;
        } else {
            saveMessage(getText("user.updated.byAdmin", args));
            return INPUT;
        }
   }
    

    public String changePassword()throws Exception {
    	User loggedInUser = SecurityUtil.getLoggedInUser();
    	setUser(loggedInUser);
    	return SUCCESS;
    }
   
    public String updatePassword()throws Exception {
    	User user = userManager.getUser(getRequest().getParameter("user.id"));
    	user.setPassword(password);
    	user.setConfirmPassword(password);
    	userManager.saveUser(user);
    	return SUCCESS;
    }
    public String showCandidateDetail() throws Exception{
    	User loggedInUser = SecurityUtil.getLoggedInUser();
    	setUser(loggedInUser);
    	//setEvents(eventService.getAllEvent());  
    	/*listofmap = new ArrayList<Map<String,String>>();
	    Map map = new HashMap<String, String>();
	    map.put("eswar", "/images/404.jpg");
	    map.put("ws1", "/images/404.jpg");
	    map.put("c12", "/images/404.jpg");
	    listofmap.add(map);
	    Map map2 = new HashMap();
	    map2.put("dsds2", "/images/404.jpg");
	    map2.put("esss12", "/images/404.jpg");
	    map2.put("fsdd", "/images/404.jpg");
	    listofmap.add(map2);*/
    	return SUCCESS;
    }
    
    public String changeProfilePicture() throws Exception{
    	User user = userManager.getUser(getRequest().getParameter("user.id"));
    	
    	
    	  // the directory to upload to
        String uploadDir = ServletActionContext.getServletContext().getRealPath("/resources")
                + "/" + getRequest().getRemoteUser() + "/";

        // write the file to the file specified
        File dirPath = new File(uploadDir);

        if (!dirPath.exists()) {
            dirPath.mkdirs();
        }

        //retrieve the file data
        InputStream stream = new FileInputStream(upload);

        //write the file to the file specified
        OutputStream bos = new FileOutputStream(uploadDir + uploadFileName.replaceAll(" ", "_"));
        int bytesRead;
        byte[] buffer = new byte[8192];

        while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }

        bos.close();
        stream.close();
		String uploadDirRelativePath="/resources" + "/" + getRequest().getRemoteUser() + "/";
        user.setProfilePath(uploadDirRelativePath + uploadFileName.replaceAll(" ", "_"));
    	userManager.saveUser(user);
    	return SUCCESS;
    }
    public String showCandidateList() throws Exception {
    	setUser(new User());
    	
    	Locale locale = getRequest().getLocale();
		System.out.println("local===================="+locale);
		String userString = userManager.getCandidateGridList(locale);
		System.out.println("emailConfigString================"+userString);
		getRequest().setAttribute("userGridString", userString);
//        users = userManager.getAllCandidates();
        
        
        return SUCCESS;
    }
    
    
    public String showCreateCandidate() throws Exception{
    	user=new User();
    	user.addRole(new Role(Constants.USER_ROLE));
    	setClassYears(classYearService.getAllClassYear());
    	setSections(sectionService.getAllSection());
    	return SUCCESS;
    }

    /**
     * Grab the user from the database based on the "id" passed in.
     *
     * @return success if user found
     * @throws IOException can happen when sending a "forbidden" from response.sendError()
     */
    public String editCandidate() throws IOException,Exception {
        HttpServletRequest request = getRequest();
        boolean editProfile = (request.getRequestURI().indexOf("editProfile") > -1);
        setClassYears(classYearService.getAllClassYear());
    	setSections(sectionService.getAllSection());
        // if URL is "editProfile" - make sure it's the current user
        if (editProfile && ((request.getParameter("id") != null) || (request.getParameter("from") != null))) {
            ServletActionContext.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
            log.warn("User '" + request.getRemoteUser() + "' is trying to edit user '" +
                    request.getParameter("id") + "'");
            return null;
        }

        // if a user's id is passed in
        if (id != null) {
            // lookup the user using that id
            user = userManager.getUser(id);
        } else if (editProfile) {
            user = userManager.getUserByUsername(request.getRemoteUser());
        } else {
            user = new User();
            //have to change by INST_ADMIN_ROLE;
            user.addRole(new Role(Constants.USER_ROLE));
        }

        if (user.getUsername() != null) {
            user.setConfirmPassword(user.getPassword());

            // if user logged in with remember me, display a warning that they can't change passwords
            log.debug("checking for remember me login...");

            AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
            SecurityContext ctx = SecurityContextHolder.getContext();

            if (ctx != null) {
                Authentication auth = ctx.getAuthentication();

                if (resolver.isRememberMe(auth)) {
                    getSession().setAttribute("cookieLogin", "true");
                    saveMessage(getText("userProfile.cookieLogin"));
                }
            }
        }

        return SUCCESS;
    }

	public void setSectionService(SectionService sectionService) {
		this.sectionService = sectionService;
	}

	public SectionService getSectionService() {
		return sectionService;
	}

	public void setClassYearService(ClassYearService classYearService) {
		this.classYearService = classYearService;
	}

	public ClassYearService getClassYearService() {
		return classYearService;
	}

	public void setClassYears(List<ClassYear> classYears) {
		this.classYears = classYears;
	}

	public List<ClassYear> getClassYears() {
		return classYears;
	}

	public void setSections(List<Section> sections) {
		this.sections = sections;
	}

	public List<Section> getSections() {
		return sections;
	}

	public void setEvents(List<Event> events) {
		this.events = events;
	}

	public List<Event> getEvents() {
		return events;
	}

	public void setEventService(EventService eventService) {
		this.eventService = eventService;
	}

	public EventService getEventService() {
		return eventService;
	}
}
